package org.clever.arkdemo.livestream.common.stream.infrastructure.adapter.tencent;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.clever.arkdemo.livestream.common.stream.domain.service.LiveStream;
import org.clever.arkdemo.livestream.common.stream.domain.vo.LiveStreamPath;
import org.clever.arkdemo.livestream.common.stream.domain.vo.LiveStreamPlayPath;
import org.clever.arkdemo.livestream.common.stream.domain.vo.LiveStreamPushPath;
import org.clever.arkdemo.livestream.common.stream.infrastructure.config.TencentCloundLiveStreamConfig;
import org.clever.arkdemo.livestream.common.stream.utils.LiveStreamCodec;

import java.time.Duration;

/**
 * 腾讯云直播流。
 *
 */
public class TencentCloudLiveStream implements LiveStream {

    private TencentCloundLiveStreamConfig config;

    public TencentCloudLiveStream(TencentCloundLiveStreamConfig config) {
        this.config = config;
    }

    public static Cache<String, LiveStreamPath> cache = Caffeine.newBuilder()
            .maximumSize(100000)
            .expireAfterWrite(Duration.ofMinutes(10))
            .build();


    @Override
    public LiveStreamPath getStreamPath(String streamName, long txTime) {

        LiveStreamPath ifPresent = cache.getIfPresent(streamName);
        if (ifPresent != null) {
            if (ifPresent.getInvalidTime() > (System.currentTimeMillis() / 1000)) {
                return ifPresent;
            }
        }

        if (txTime <= 100000) {
            txTime = (System.currentTimeMillis() + config.getTimeout()) / 1000;
        }

        String pushDomain = config.getPushDomain();
        LiveStreamPath streamPath = new LiveStreamPath();
        LiveStreamPushPath pushPath = new LiveStreamPushPath();
        String pushSignature = getSignature(config.getPushSecretKey(), streamName, txTime);
        pushPath.setRtmp(getRtmpUrl(pushDomain, streamName, pushSignature, txTime));
        pushPath.setObsKey(getObsKey(streamName, pushSignature, txTime));
        pushPath.setObsPath(getObsPath(streamName));

        streamPath.setPushPath(pushPath);

        String playDomain = config.getPlayDomain();
        String playSignature = getSignature(config.getPlaySecretKey(), streamName, txTime) ;
        LiveStreamPlayPath playPath = new LiveStreamPlayPath();
        playPath.setRtmp(getRtmpUrl(playDomain, streamName, playSignature, txTime));
        playPath.setFlv(getFlvUrl(playDomain, streamName, playSignature, txTime));

        streamPath.setPlayPath(playPath);
        streamPath.setInvalidTime(txTime);
        cache.put(streamName, streamPath);
        return streamPath;
    }

    /// rtmp://210931.push.tlivecloud.com/live/1000?txSecret=69d6341665f9158adb10da5b4c9998ab&txTime=67CFCA4B

    private String getRtmpUrl(String path, String streamName , String signature, long txTime) {
//        String rtmpUrl = "rtmp://" + config.getPushDomain() + "/"+streamName+"/" + streamName;
        String appName = config.getAppName();
        StringBuilder rtmpUrl = new StringBuilder();
        rtmpUrl.append("rtmp://").append(path).append("/")
                .append(appName).append("/").append(streamName);
        if (signature != null && !signature.isEmpty()) {
            rtmpUrl.append("?txSecret=").append(signature)
                    .append("&txTime=").append(Long.toHexString(txTime).toUpperCase());
        }

        return rtmpUrl.toString();
    }

    private String getFlvUrl(String path, String streamName, String signature, long txTime) {
        // http://play-stream.icqim.com/live/1000.flv?txSecret=f92950de8877893276efe3fbb3196272&txTime=67CFCA4B
        String appName = config.getAppName();
        StringBuilder flvUrl = new StringBuilder();
        flvUrl.append("http://").append(path).append("/")
                .append(appName).append("/").append(streamName).append(".flv");

        if (signature != null && !signature.isEmpty()) {
            flvUrl.append("?txSecret=").append(signature)
                    .append("&txTime=").append(Long.toHexString(txTime).toUpperCase());
        }

        return flvUrl.toString();
    }

    private String getObsKey(String streamName, String signature, long txTime) {
        // 1000?txSecret=69d6341665f9158adb10da5b4c9998ab&txTime=67CFCA4B
        return streamName + "?" + "txSecret=" + signature + "&txTime=" + Long.toHexString(txTime).toUpperCase();
    }

    private String getObsPath(String streamName) {
        // rtmp://210931.push.tlivecloud.com/live/
        return "rtmp://" + config.getPushDomain() + "/" + config.getAppName() + "/";
    }

    private String getSignature(String key, String streamName, long txTime) {
        if ("md5".equals(config.getEncryptType())) {
            return LiveStreamCodec.md5(key, streamName, Long.toHexString(txTime).toUpperCase());
        } else if ("sha256".equals(config.getEncryptType())) {
            return LiveStreamCodec.sha256(key, streamName, Long.toHexString(txTime).toUpperCase());
        } else {
            throw new RuntimeException("不支持的加密类型");
        }
    }



}
